package algoritmo;
import java.util.Random;


public class CromosomaFuncionUno extends Cromosoma{

	
	// extremos del intervalo considerado
	// para los valores del dominio
	float	xmin;//Debe ser un array por si hay varias variables
	float	xmax;
	int numGenes;
	int[] longitudCadaGen;
	int numVariables;
	float tol;
	int longitudCromosoma;
	float maximo;//Es el valor maximo de la generacion. Se usa para retocar la aptitud.
					//FIXME al pintar hay que tenerlo en cuenta
	float aptitudRetocada;
	
	public void pinta() {
		System.out.println("APTITUD: "+  (aptitud));
		System.out.println("FENOTIPO: "+fenotipo[0]);
		String g="";
		for (int i=0;i<longitudCromosoma;i++){
			g = g + genes[i] + ' ';
		}
		System.out.println(g+"\n");
		
	}

	
	public CromosomaFuncionUno(){
		
	}
	
	public void inicializaCromosoma(float xmin, float xmax,int numGenes, int numVariables,float tol) {
		this.xmin = xmin;
		this.xmax = xmax;
		this.numGenes = numGenes;
		//this.longitudCadaGen = /*se calcula con min y max de cada variable: x,y,z...*/
		this.numVariables = numVariables;
		this.tol = tol;
		longitudCromosoma = calculaLongitud();
		
		genes = new boolean[longitudCromosoma];	
		Random r = new Random();
		for(int i=0;i<longitudCromosoma;i++){
			if( r.nextDouble() < 0.5)
				genes[i] = true;
			else
				genes[i] = false;
		}
		
		fenotipo = fenotipo();
		aptitud = evalua();
	}
	
	public void inicializaParcialCromosoma(float xmin, float xmax,int numGenes, int numVariables,float tol) {
		this.xmin = xmin;
		this.xmax = xmax;
		this.numGenes = numGenes;
		//this.longitudCadaGen = /*se calcula con min y max de cada variable: x,y,z...*/
		this.numVariables = numVariables;
		this.tol = tol;
		longitudCromosoma = calculaLongitud();
		
		fenotipo = new float[1];
		genes = new boolean[longitudCromosoma];	
	}

	public int calculaLongitud() {
		float longitud = (float) (Math.log(1+((xmax-xmin)/tol))/Math.log(2));
		return (int) Math.ceil(longitud);//Redondeas hacia arriba siempre si hay decimales
	}
		
	public int binomio(){//el valor del individuo
		int exponente = 0;
		int resul = 0;
		for(int i=longitudCromosoma-1;i>=0;i--){
			if( genes[i] == true )
				resul  = (int) (resul + Math.pow(2,exponente));
			exponente++;
		}
		return resul;
	}
	
	public float[] fenotipo(){
		float[] resul = new float[1];
		resul[0] = (float) (xmin + binomio() * ( (xmax-xmin)/(Math.pow(2, longitudCromosoma) - 1) ) );
		return resul;
	}
	
	
	public float evalua() { 
		float[]x = fenotipo();
		float numerador = (float) Math.sin(x[0]);
		float denominador = (float) (1 + (Math.sqrt(x[0])) + (Math.cos(x[0])/(1+x[0])));
		return numerador / denominador;
	}
	
//	public float evalua() { 
//		float x = fenotipo();
//		float numerador = x - 5;
//		float denominador = (float) (2 + Math.sin(Math.toRadians(x)));
//		return Math.abs(numerador / denominador);
//	}
	
//	public float evalua(){
//		float x = fenotipo();
//		return 5-x;
//	}
	
	
	public void copia(Cromosoma nuevo) {
		((CromosomaFuncionUno)nuevo).xmin = this.xmin;
		((CromosomaFuncionUno)nuevo).xmax = this.xmax;
		((CromosomaFuncionUno)nuevo).numGenes = this.numGenes;
		((CromosomaFuncionUno)nuevo).numVariables = this.numVariables;
		((CromosomaFuncionUno)nuevo).tol = this.tol;
		((CromosomaFuncionUno)nuevo).longitudCromosoma = this.longitudCromosoma;
		((CromosomaFuncionUno)nuevo).maximo = this.maximo;
		((CromosomaFuncionUno)nuevo).aptitudRetocada = this.aptitudRetocada;
		
		nuevo.fenotipo = new float[1];
		nuevo.setFenotipo(this.fenotipo);
		nuevo.setAptitud(this.aptitud);
//		if(nuevo.fenotipo==0 || nuevo.aptitud==0)
//			System.out.println("Cero");
		nuevo.setPuntuacion(this.puntuacion);
		nuevo.setPuntuacionAcumulada(this.punt_acum);
		((CromosomaFuncionUno) nuevo).setAptitudMaxima(maximo);
		
		nuevo.genes = new boolean[longitudCromosoma];
		for(int i=0;i<longitudCromosoma;i++){
			nuevo.setGen(i, this.genes[i]);
		}
		
		
	}
	
	public int getLongitudCromosoma(){
		return longitudCromosoma;
	}

	
	public float getXmin(){
		return xmin;
	}
	
	public float getXmax(){
		return xmax;
	}

	public int getNumGenes() {
		return numGenes;
	}

	public int getNumVariables() {
		return numVariables;
	}
	
	public float getMax(){
		return maximo;
	}

	public void setAptitudMaxima(float max) {
		maximo = max;
		
	}
	
	public float getAptitudRetocada() {
		return aptitudRetocada;
	}

	public void setAptitudRetocada(float aptitudRetocada) {
		this.aptitudRetocada = aptitudRetocada;
	}
	
	
}
